DevOps
CICD
K8s
Docker
Taint the worker node g8node1 to be Unschedulable. Once done, create a pod called dev-redis
, image redis:alpine
to ensure workloads are not scheduled to this worker node. Finally, create a new pod called prod-redis
and image redis:alpine
with toleration to be scheduled on g8node1.
這題也是個Pod Scheduling
的問題,但是它和我們第一題學的label
的方式明顯不同,題目要求我們將g8node1
標註為Unschedulable
,且第一個Pod
不可以被分派到g8node1
上,但是第二個創建的Pod
卻必須assing到g8node1
上,這樣特殊的Scheduling方式要如何辦到呢?就需要依靠K8s
中的Taint&Toleration
啦~ 按照慣例,我們先來介紹一下這是個甚麼東西吧~
所謂的
Taints
即是允許Node
抵制 (repel) 某些Pod
,使Pod
無法在該節點上運行
而Tolerations
則是搭配Taints
一同使用,擁有Tolerations
的Pod可以被分派到擁有Taints
的節點上,但前提是兩者能夠匹配
Taints
和Tolerations
共同使用,以避免將Pod
調度到不適合的節點上。一個或多個Taints
應用於Node
,表示該節點不應接受任何不能容忍Taints
的Pod
。
Taints
用於Node
;Tolerations
則用於Pod
要使用Taints
可以透過kubectl taint
指命:
## 新增 taint
$ kubectl taint nodes <node-name> <key>=<value>:<effect>
## 例如
$ kubectl taint nodes g8node1 size=large:NoSchedule
## 刪除 taint
$ kubectl taint nodes <node-name> <key>=<value>:<effect>-
## 例如
$ kubectl taint nodes g8node1 size=large:NoSchedule-
effect
欄位是指:當Pod
因為此Taint
而無法調度到該節點上的時候,該怎麼處理,一共有三種處理方式:
後面會介紹這三種的差別
若要讓Pod
可以被分派到有taint
的Node
上,則需要宣告Tolerations
。下面兩個Tolerations
的設定都可以容忍上述例子的taint
,因此可被調度到g8node1
節點上:
tolerations:
- key: "size"
operator: "Equal"
value: "large"
effect: "NoSchedule"
或
tolerations:
- key: "size"
operator: "Exists"
effect: "NoSchedule"
所有的
value
都要以雙引號""
標註
Pod
的Toleration
宣告中的key
和effect
需要與Taint
的設定保持一致,並滿足以下條件之一:
operator
的值是Exists
(無須指定value)operator
的值是Equal
且value值相等若無指定
operator
,則effect
預設為Equal
上面的例子使用了NoSchedule
的effect
,意思是:除非Pod
明確宣告可以容忍這個Taint
,否則不會被調度到g8node1
上。除了NoSchedule
外,還可以使用PreferNoSchedule
的effect
,意思是優先,一個Pod
若沒有宣告容忍這個Taint
,則K8s
會盡量避免把該Pod
調度到這個節點上,但不是強制的。
K8s
允許在同個Node
上設定多個Taints
;當然也可以在Pod
上設定多個Tolerations
。K8s
調度器處理多個Taints
和Tolerations
的邏輯順序是這樣:首先列出節點中所有的Taints
,忽略Pod
的Toleration
能符合的部分,剩下沒有忽略的Taints
就是對Pod
的效果了。下面有幾種特殊情況:
Taints
中存在effect=NoSchedule
,則調度器不會把該Pod
調度到此節點上Taints
中沒有effect=NoSchedule
,但有PreferNoSchedule
,則會試著不把該Pod調度到此節點Taints
中有effect=NoExcute
,並且該Pod
已經在此節點上運行,則會被驅逐;若沒有在此節點上運行,也不會再被調度到此節點上Taint
和Toleration
是一種處理節點驅逐Pod
或讓Pod
避開不適合節點的彈性調度方式,常見的使用Taint
和Toleration
的應用場景有:
Node
做trobleshooting)有沒有發現我們創建的Pod都不會運行在
Control Plane
節點上,聰明的你肯定發現原因了!沒錯,就是因為Control Plane
節點default都有Taint
在上面,因此無法在上面運行Pod哦~
可以用kubectl describe node
指令,觀察Control Plane
上的Taint
欄位資訊~
回到題目,這題就是Taint
和Toleration
的應用題型,但值得注意的是,這題只在單一節點上設定Taint
是不行的,因為Taint
只能確保沒有Toleration
的Pod
不會被調度到該Node
上,但是不能保證有Toleration
的Pod
一定可以被調度到有Taint
的Node
上
可能有點繞口,但這兩者是有差別的,你可以想像A,B兩節點,只有A有Taint,B沒有,有一個Pod要啟動,它有A的Toleration,所以它可以在A上運行,但其實它也可以在B上運行,兩者是沒有衝突的
因此,我們需要在每一節點上設置不同的Taint
,Pod
才能依照Toleration
的設定調度到目標節點上。
其實想要讓某一pod一定運行在某一節點上,在K8s中有更聰明的方法,就是
Node Affinity
。但是這題限定我們使用Taint&Toleration
,而且我們還沒學過Node Affinity
,就先這樣吧~
想法如下:
g8node1
和g8node2
g8node2
但無法容忍g8node1
g8node1
但無法容忍g8node2
首先將g8node1
和g8node2
加上Taint
$ kubectl taint nodes g8node1 env_type=production:NoSchedule
$ kubectl taint nodes g8node2 other_type=development:NoSchedule
創建第一個Pod
,讓它無法被調度到g8node1
上,那就讓它能容忍g8node2
的Taint
$ kubectl run dev-redis --image=redis:alpine --restart=Never --dry-run=client -o yaml > q10-1.yaml
$ vim q10-1.yaml
## 加上toleration,如下圖
創建第二個Pod
,讓它可以被調度到g8node1
上,讓它能容忍g8node1
的Taint
$ kubectl run prod-redis --image=redis:alpine --restart=Never --dry-run=client -o yaml > q10-2.yaml
$ vim q10-2.yaml
## 加上toleration,如下圖
接著創建這兩個Pod
,以kubectl get po -o wide
命令即可看見調度的成果
因為我們的集群環境只有兩個節點,所以其實不用這麼麻煩,
g8node2
根本不用Taint
。但是考試時的環境可能不會只有兩個Node
,所以建議練習時還是要作完整的考量哦~
今天介紹了K8s
中更進階的Scheduling方式--Taint
和Toleration
,要特別注意它們的使用時機和各自作用的物件喔~ 好啦,今天就到這囉~ 謝謝大家~
You can find me on